package org.six11.olive.collabclient.server;

import java.io.PrintWriter;
import java.util.Collection;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.six11.util.io.Message;
import org.six11.util.adt.MultiState;
import org.six11.util.adt.SynchronizedQueue;

/**
 * This is the handler used to send messages to clients. Each client has a 'download' thread which
 * hits this handler. If the ping handler has no data, it holds onto the connection for a while but
 * will wake up if new data becomes available. Messages are flushed from the user's message queue
 * (getMessageQueue(Person)) and written to the wire. The client then immediately reconnects to get
 * more data.
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 */
public class PingHandler extends AppletMessageHandler {

  private XMLOutputter outputter;
  private StateTool tool;
  /**
   * @param state
   */
  public PingHandler(MultiState state) {
    super(state);
    tool = new StateTool(state);

    Format pretty = Format.getPrettyFormat();
    outputter = new XMLOutputter(pretty);
  }

  /**
   * 
   */
  @Override
  public void handle(Message m, String sessionID, PrintWriter out) {
    SynchronizedQueue<Message> q = tool.getMessageQueue(sessionID, true);
    Collection<Message> outbound = null;
    synchronized (q) {
      // allow up to 5 seconds for a message to appear, and get out of synchronized block ASAP
      if (q.isEmpty()) {
        try {
          q.wait(5000);
        } catch (InterruptedException ex) {
          ex.printStackTrace();
        }
      }
      if (!q.isEmpty()) {
        outbound = q.getAll(true);
      }
    }
    if (outbound != null) {
      Element root = new Element("messages");
      Document messages = new Document(root);
      for (Message outMsg : outbound) {
        try {
          root.addContent(outMsg.getRoot().detach());
        } catch (IllegalStateException ex) {
          log("Some sort of error happened while handling ping request. Bye!");
	  ex.printStackTrace();
        }
      }
      out.write(outputter.outputString(messages));
      out.flush();
      out.close();
    }
  }

}
